﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using System.Collections.ObjectModel;
using System.Xml.Linq;
using Csla.Rules.CommonRules;

namespace Agnes.MyDocsLib
{
    /// <summary>
    /// 文章目录Model
    /// </summary>
    [Serializable]
    public class Catalog : ModelBase<Catalog>, IArticleNode
    {

        #region Property

        /// <summary>
        /// 文章所属分类
        /// </summary>
        public Catalog ParentCatalog { get; set; }

        #endregion

        #region Csla 属性

        public static readonly PropertyInfo<Guid> IdProperty = RegisterProperty<Guid>(c => c.Id);
        /// <summary>
        /// 唯一Id
        /// </summary>
        public Guid Id
        {
            get { return GetProperty(IdProperty); }
            set { SetProperty(IdProperty, value); }
        }

        public static readonly PropertyInfo<string> TitleProperty = RegisterProperty<string>(c => c.Title);
        /// <summary>
        /// 目录标题
        /// </summary>
        public string Title
        {
            get { return GetProperty(TitleProperty); }
            set { SetProperty(TitleProperty, value); }
        }

        public static readonly PropertyInfo<ObservableCollection<IArticleNode>> ChildsProperty = RegisterProperty<ObservableCollection<IArticleNode>>(c => c.Childs);
        /// <summary>
        /// 目录下的子节点(包括目录和文章)
        /// </summary>
        public ObservableCollection<IArticleNode> Childs
        {
            get { return GetProperty(ChildsProperty); }
            private set { SetProperty(ChildsProperty, value); }
        }

        #endregion

        #region Csla Method

        public override void Delete()
        {
            if (ParentCatalog != null)
            {
                ParentCatalog.Childs.Remove(this);
            }
            //base.Parent.RemoveChild(this);
        }

        /// <summary>
        /// DoCreate
        /// </summary>
        /// <param name="createParam"></param>
        protected override void DoCreate(object createParam)
        {
            base.DoCreate(createParam);
            using (BypassPropertyChecks)
            {
                Id = Guid.NewGuid();
                Title = "";
                Childs = new ObservableCollection<IArticleNode>();
                ParentCatalog = null;
            }
        }

        /// <summary>
        /// DoFetch
        /// </summary>
        /// <param name="fetchParam"></param>
        protected override void DoFetch(object fetchParam)
        {
            base.DoFetch(fetchParam);
            using (BypassPropertyChecks)
            {
                XElement el = fetchParam as XElement;
                Title = el.Attribute("Title").Value;
                Id = Guid.Parse(el.Attribute("Id").Value);
                Childs = new ObservableCollection<IArticleNode>();
                foreach (XElement i in el.Elements())
                {
                    IArticleNode tmp = null;
                    if (i.Name == "Catalog")
                    {
                        tmp = Catalog.FetchAsChild(i);
                        (tmp as Catalog).ParentCatalog = this;
                    }
                    else if (i.Name == "Article")
                    {
                        tmp = Article.FetchAsChild(i);
                        (tmp as Article).ParentCatalog = this;
                    }
                    Childs.Add(tmp);
                }
            }
            DataPortal_Update();
        }

        private XElement GetXml()
        {
            XElement el = new XElement("Catalog",
                new XAttribute("Title", Title),
                new XAttribute("Id", Id.ToString()));
            foreach (IArticleNode i in Childs)
            {
                if (i is Catalog)
                {
                    (i as Catalog).SaveToXml(t => el.Add(t));
                }
                else if (i is Article)
                {
                    (i as Article).SaveToXml(t => el.Add(t));
                }
            }
            return el;
        }

        /// <summary>
        /// SaveToXml
        /// </summary>
        /// <param name="Save"></param>
        public void SaveToXml(Action<XElement> Save)
        {
            DataPortal.UpdateChild(this);
            Save(GetXml());
        }

        #endregion

        #region Validation

        protected override void AddBusinessRules()
        {
            base.AddBusinessRules();
            AddTitleRule();
        }

        private void AddTitleRule()
        {
            var r = new Lambda(TitleProperty, t =>
                {
                    Catalog h = t.Target as Catalog;
                    if (string.IsNullOrEmpty(h.Title))
                    {
                        t.AddErrorResult("目录名不能为空");
                    }
                });

            BusinessRules.AddRule(r);
        }

        #endregion


        /// <summary>
        /// GetPath
        /// </summary>
        /// <returns></returns>
        public string GetPath()
        {
            string res = "";

            Catalog tmp = ParentCatalog;
            while (tmp != null)
            {
                res = tmp.Title + "/" + res;
                tmp = tmp.ParentCatalog;
            }

            res = "我的知识库/" + res;
            return res;
        }
    }
}
